package service

import (
	"bufio"
	"fmt"
	"net"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
)

// SetKeepAliveOptions enables TCP keep-alive on the connection
func setKeepAliveOptions(conn net.Conn) error {
	tcpConn, ok := conn.(*net.TCPConn)
	if !ok {
		return fmt.Errorf("无法转换为 TCPConn 类型")
	}

	// 启用 TCP KeepAlive
	err := tcpConn.SetKeepAlive(true)
	if err != nil {
		return fmt.Errorf("启用 keep-alive 失败: %v", err)
	}

	// 注意：没有办法在 Go 中直接设置 TCP keep-alive 参数（如 idle time、探测间隔等），
	// 这些参数通常由操作系统的 TCP/IP 堆栈管理。可以通过系统级别配置来调整。

	// 在大多数操作系统中，keep-alive 的空闲时间、探测间隔等由 OS 控制。
	// 对于 Linux，可能需要调整 sysctl 参数，例如：
	//   - net.ipv4.tcp_keepalive_time (空闲时间)
	//   - net.ipv4.tcp_keepalive_intvl (探测间隔)
	//   - net.ipv4.tcp_keepalive_probes (失败探测次数)
	// 这些配置通常不需要在 Go 中直接设置。

	return nil
}

func Sock() error {
	// 定义最大重试次数
	const maxRetries = 5
	retryInterval := 2 * time.Second // 每次重试的间隔

	// 尝试连接到目标服务器，带重试逻辑
	var conn net.Conn
	var err error
	for attempt := 1; attempt <= maxRetries; attempt++ {
		conn, err = net.Dial("tcp", "129.204.125.7:28888")
		if err == nil {
			break // 成功连接，退出重试循环
		}
		fmt.Printf("第 %d 次尝试连接失败，错误：%s\n", attempt, err)
		if attempt < maxRetries {
			time.Sleep(retryInterval)
		}
	}
	if err != nil {
		return fmt.Errorf("无法连接到服务器，已重试 %d 次，最后错误：%s", maxRetries, err)
	}
	defer conn.Close() // 程序结束时自动关闭连接

	// 启用 keep-alive 功能
	err = setKeepAliveOptions(conn)
	if err != nil {
		return fmt.Errorf("启用 Keep-Alive 失败: %v", err)
	}

	// 发送初始消息，带重试逻辑
	message := "IkxjNNMMOO288783KOIYYT112233445556667788:::>>>???PPPOO{{AAAQ!\n"
	for attempt := 1; attempt <= maxRetries; attempt++ {
		_, err = conn.Write([]byte(message))
		if err == nil {
			break // 消息发送成功，退出重试循环
		}
		fmt.Printf("第 %d 次发送消息失败，错误：%s\n", attempt, err)
		if attempt < maxRetries {
			time.Sleep(retryInterval)
		}
	}
	if err != nil {
		return fmt.Errorf("消息发送失败，已重试 %d 次，最后错误：%s", maxRetries, err)
	}
	log.Info("消息已发送:", message)

	// 创建一个定时器，每30秒发送一次心跳消息 "O"
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop() // 确保 ticker 在函数结束时停止

	// 读取服务器的响应，带重试逻辑
	reader := bufio.NewReader(conn)
	for {
		select {
		case <-ticker.C: // 每30秒触发一次心跳
			// 回复心跳消息 "O"
			_, err := conn.Write([]byte("O\n"))
			if err != nil {
				log.Info("发送心跳消息错误:", err)
				// 如果发送失败，尝试重连
				return RetryConnection()
			}
			// log.Info("已回复心跳: O")

		default:
			msg, err := reader.ReadString('\n') // 逐行读取响应
			if err != nil {
				if err.Error() != "EOF" {
					log.Info("读取消息错误:", err)
					// 如果读取错误，尝试重连
					return RetryConnection()
				}
				return nil // 如果是 EOF（连接关闭），退出
			}
			if msg != "" && msg != "b\n" {
				log.Info("接收到消息:", msg)
				// 处理接收到的消息
				go func() {
					ReviceSell(strings.TrimSpace(msg))
				}()
			}

			// 回复 "O" 给服务器
			_, err = conn.Write([]byte("O\n"))
			if err != nil {
				log.Info("发送回复消息错误:", err)
				// 如果发送失败，尝试重连
				return RetryConnection()
			}
			// log.Info("已回复: O")
		}
	}
}

// RetryConnection 封装了重试连接的逻辑
func RetryConnection() error {
	const maxRetries = 5
	retryInterval := 2 * time.Second

	// 尝试重新连接
	for attempt := 1; attempt <= maxRetries; attempt++ {
		fmt.Printf("尝试重新连接... 第 %d 次\n", attempt)
		conn, err := net.Dial("tcp", "129.204.125.7:28888")
		if err == nil {
			// 如果连接成功，则返回
			defer conn.Close()
			log.Info("重新连接成功！")
			return nil
		}
		fmt.Printf("第 %d 次重连失败，错误：%s\n", attempt, err)
		if attempt < maxRetries {
			time.Sleep(retryInterval)
		}
	}
	return fmt.Errorf("重试连接失败，已尝试 %d 次", maxRetries)
}
